package com.fox0g.netty;


import com.fox0g.websocket.WebSocketHandler;
import com.fox0g.service.*;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.socket.SocketChannel;
import io.netty.util.CharsetUtil;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @program: buildTest
 * @Date: 2022-08-06 13:46
 * @author: Fox0g
 * @description:
 */
@Component
@ChannelHandler.Sharable
@Slf4j
public class NettyServerHandler extends SimpleChannelInboundHandler<String> {

//@Autowired
//AudioService audioService;
//@Autowired
//    KongtiaoService kongtiaoService;
//@Autowired
//    NongyeService nongyeService;
//    @Autowired
//    QueuService queuService;
    @Autowired
    WebSocketHandler webSocketHandler;
//    @Autowired
//    ShengxiangService shengxiangService;

    @Autowired
    FarmService farmService;

    @Autowired
    FreshfoodService freshfoodService;



    @Autowired
    SharebikeService sharebikeService;

    @Autowired
    QueuecountService queuecountService;

    @Autowired
    YsjrepeatService ysjrepeatService;

    @Autowired
    TstateService tstateService;

    @Autowired
    VirusService virusService;



    Thread thread = new Thread(()->{
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        try {
            doAllReply("AlarmonT");
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    });
    String ip;


    /**
     * 客户端断开连接时执行，将客户端信息从Map中移除
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {

        log.info("客户端断开连接：{}", getClientIp(ctx.channel()));
        NettyChannelMap.remove((SocketChannel) ctx.channel());
        System.out.println("开启定时");
        webSocketHandler.send("开启定时");
    }

    /**
     * @Description 客户端连接时执行，将客户端信息保存到Map中
     * @param ctx
     * @Date
     * @Author Fox0g
     * @return
     **/
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {


        log.info("有新的客户端连接：{}", getClientIp(ctx.channel()));
        String clientIp = getClientIp(ctx.channel());
        NettyClient client = new NettyClient((SocketChannel) ctx.channel(), getClientIp(ctx.channel()));
        NettyChannelMap.add(clientIp, client);
        //向硬件传输初始化数据
        webSocketHandler.send("Reconnect");
        webSocketHandler.send("结束定时");
//        while (true){
//            LocalTime now = LocalTime.now();
//            Thread.sleep(1000);
//            doAllReply("HWtime" + now.toString().substring(0,8) + "Z");
//        }
//        new Thread(new Runnable() {
//            @Override
//            public void run() {
//                while (true){
//                    LocalTime now = LocalTime.now();
//                    try {
//                        Thread.sleep(1000);
//                    } catch (InterruptedException e) {
//                        throw new RuntimeException(e);
//                    }
////                    doAllReply("HWtime" + now.toString().substring(0,8) + "Z");
//                    try {
//                        webSocketHandler.send("localtime");
//                    } catch (IOException e) {
//                        throw new RuntimeException(e);
//                    }
//                }
//
//            }
//        }).start();



    }

    /**
     * @Description 收到消息时执行，根据消息类型做不同的处理
     * @param ctx
     * @param message
     * @return
     **/
    @Override
    public void messageReceived(ChannelHandlerContext ctx, String message) throws Exception {
        //根据T来分割存储的原因是：当有多台设备同时向服务器发送数据帧时可能会产生堵塞，导致多条数据帧拼接在一块的情况
        String[] Msg = message.split("Z");
//        doAllReply(message,ctx);
        //A______BA______B
        //A______ A______


        for (String msg : Msg) {
            msg = msg + "Z";
            //打印数据源 以及内容
            System.out.println("客户端:" + getClientIp(ctx.channel()) + "==>" + msg);

            //向所有客户端转发 当前 数据
            Thread.sleep(100);

            if (!msg.equals("Stay connected...T")) {
                doAllReply(msg,ctx);
            }
            //解析、处理 数据
            virusService.HandleMessage(msg);
        }
//        if (message.matches("HHT[0-9]+.[0-9]H[0-9]+.[0-9]LS[0-9]+H")) {
//            String arrnews1[] = message.split("T");
//            String arrnew2[] = arrnews1[1].split("H");
//            String arrnew3[] = arrnew2[1].split("LS");
////            String T = arrnew2[0];  //截取温度
////            String H = arrnew3[0];  //截取湿度
////            String LS = arrnew3[1]; //截取光敏度
////            System.out.println("时间" + arrnew2[0] + "温度" + arrnew3[0] + "湿度" + arrnew3[1]);
//            shengxiangService.HandleMessage("T" + arrnew2[0]);
//            shengxiangService.HandleMessage("Hd" + arrnew3[0]);
//            shengxiangService.HandleMessage("LS" + arrnew3[1]);
//        }
//        if(message.matches("HH[0-9]+H")){
//            shengxiangService.HandleMessage(message);
//        }
//        farmService.HandleMessage(message);
    }

    /**
     * @description: TODO
     * @param ctx
     * @param cause
     * @return: void
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        log.info("抛出异常执行，包括客户端断开连接时，会抛出IO异常");
        cause.printStackTrace();
    }

    public void doServerReply(String msg) throws IOException {
        Socket socket = new Socket("localhost", 10086);
        OutputStream outputStream = socket.getOutputStream();
        outputStream.write(msg.getBytes(CharsetUtil.UTF_8));
        outputStream.flush();
    }

    /**
     * @description: 当收到客户端的消息后，向单独客户端发送消息
     * @param ctx
     * @return: void
     */
    public void doReply(ChannelHandlerContext ctx,String msg) {
        ctx.channel().writeAndFlush(msg);
        System.out.println("服务器返回数据--"+msg);
    }
    /**
     * 向所有客户端转发消息
     *
     * @param msg
     * @param ctx
     */
    public void doAllReply(String msg, ChannelHandlerContext ctx) throws InterruptedException {
        System.out.println("转发成功");
        System.out.println("------");
        String clientIp = getClientIp(ctx.channel());
        System.out.println("clientIp:"+clientIp);
        for (NettyClient value : NettyChannelMap.map.values()) {
            InetAddress address = value.getChannel().remoteAddress().getAddress();//获取远程连接的ip地址
            String string = address.toString();
            String replace = string.replace("/", "");
            System.out.println("replace:"+replace);
            if (clientIp.equals(replace)){
                continue;
            }
            System.out.println("服务器=>客户端:"+value.getChannel().remoteAddress().getAddress()+"=>数据:"+msg);
            value.getChannel().writeAndFlush(msg);
        }
        System.out.println("------");
        System.out.println();

    }

    public void doAllReply(String msg) throws InterruptedException {
//        Thread.sleep(1000);
        System.out.println("------");
        for (NettyClient value : NettyChannelMap.map.values()) {
            //value.getChannel().remoteAddress().getAddress()获取远程连接的ip地址
            System.out.println("服务器=>客户端:"+value.getChannel().remoteAddress().getAddress()+"=>数据:"+msg);
            value.getChannel().writeAndFlush(msg);
        }
        System.out.println("------");
        System.out.println();

    }

    /**
     * @Description 获取客户端IP
     * @param channel
     * @return
     **/
    private String getClientIp(Channel channel) {
        InetSocketAddress inetSocketAddress = (InetSocketAddress) channel.remoteAddress();
        String clientIP = inetSocketAddress.getAddress().getHostAddress();
        return clientIP;
    }

    /**
     * @Description 当有新的客户端连接的时候，用于保存客户端信息
     * @return
     **/
    public static class NettyChannelMap {

        //使用一个线程安全的map集合，存储每一个客户端的id和NettyClient（SocketChannel通道和ip地址）
        public static Map<String, NettyClient> map = new ConcurrentHashMap<>();

        //添加一个客户端
        public static void add(String clientId, NettyClient client) {
            map.put(clientId, client);
        }
        //根据id获取客户端信息
        public static NettyClient get(String clientId) {
            return map.get(clientId);
        }
        //根据socketChannel连接通道删除map集合中的元素
        public static void remove(SocketChannel socketChannel) {
            for (Map.Entry entry : map.entrySet()) {
                if (((NettyClient) entry.getValue()).getChannel() == socketChannel) {
                    map.remove(entry.getKey());
                }
            }
        }
    }

    /**
     * @Description 封装客户端的信息
     * @return
     **/
    @Data
    public static class NettyClient {

        /**客户端与服务器的连接*/
        private SocketChannel channel;

        /**ip地址*/
        private String clientIp;

        // ......

        public NettyClient(SocketChannel channel, String clientIp) {
            this.channel = channel;
            this.clientIp = clientIp;
        }

    }

}
